package com.atguigu.gulimall.search.thread;

import javax.sql.rowset.CachedRowSet;
import java.util.concurrent.*;

/**
 * @author Administrator
 * @create 2021/12/6 10:23
 */
public class ThreadTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main............start......");
//        CompletableFuture<Void> future = CompletableFuture.runAsync(new Runnable() {
//            @Override
//            public void run() {
//                System.out.println("当前线程：" + Thread.currentThread().getId());
//                int i = 10 / 2;
//                System.out.println("执行结果：" + i);
//            }
//        }, executor);
        /**
         * 方法完成后的感知
         */
//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 0;
//            System.out.println("执行结果：" + i);
//            return i;
//        }, executor).whenComplete((res,excption)->{
//            //虽然能得到异常信息，但是没法修改返回数据。类似于一个监听器，监听异常。
//            System.out.println("返回结果："+res+"; 异常："+excption);
//        }).exceptionally(throwable -> {
//            //可以感知异常，同时修改返回值
//            System.out.println("exceptionally异常："+throwable);
//            return 10;
//        });
        /**
         * 方法完成后的处理
         */
//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("执行结果：" + i);
//            return i;
//        }, executor).handle((res,exception)->{
//            if(res != null){
//                return res*2;
//            }
//            if(exception != null){
//                return 0;
//            }
//            return 0;
//        });

        /**
         * 线程串行化
         * 1、thenRunL：不能获取上一步的执行结果
         * 2、thenAcceptAsync：能接受上一步结果，但是无返回值
         * 3、thenApplyAsync：能接受上一步结果，有返回值
         *
         */
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }, executor).thenApplyAsync(res -> {
            System.out.println("任务2启动了..." + res);
            return "Hello" + res;
        }, executor);
        System.out.println("main......end....." + future.get());
        System.out.println("future:"+future.get());
//        executor.shutdownNow();  //关闭线程池
        System.out.println("main............end......");


    }

    public  void thread(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main............start......");
        /**
         * 1)继承 Thread
         *       Thread thread = new Thread01();
         *       thread.start();
         * 2）实现 Runnable接口
         *       Runnable runnable = new Runable01();
         *       new Thread(runnable).start();
         * 3）实现Callable接口 + FutureTask （可以拿到返回结果，可以处理异常）
         *      FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
         *      new Thread(futureTask).start();
         *      Integer i = futureTask.get();//阻塞等待整个线程执行完成，获取返回结果
         * 4) 线程池： 给线程池直接提交任务
         *      Executors.newFiexedThreadPool(3);
         *      //或者 new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit unit, workQueue, threadFactory, handler);
         *
         *      Feature:可以获取到异步结果
         * 区别：1、2不能得到返回值，3能得到返回值，但是不利于控制服务器中的线程资源。可以导致 服务器资源耗尽。
         *
         */
        /**
         * 七大参数
         *  1. corePoolSize: 池中一直保持的线程的数量，即使线程空闲。除非设置了 allowCoreThreadTimeOut
         * 2. maximumPoolSize: 池中允许的最大的线程数
         * 3. keepAliveTime: 当线程数大于核心线程数的时候，超出核心线程数的线程在最大多长时间没有接到新任务就会终止释放 ，最终线程池维持在 corePoolSize 大小
         * 4. unit: 时间单位
         * 5. workQueue: 阻塞队列，用来存储等待执行的任务，如果当前对线程的需求超过了 corePoolSize大小， 就 会放在这里 等待空闲线程执行.
         * 6. threadFactory：创建线程的工厂，比如指定线程名等
         * 7. handler：拒绝策略，如果线程满了，线程池就会使用拒绝策略。
         *
         * 运行流程：
         * 1、线程池创建，准备好 core 数量的核心线程，准备接受任务
         * 2、新的任务进来，用 core 准备好的空闲线程执行。
         * (1) 、core 满了，就将再进来的任务放入阻塞队列中。空闲的 core 就会自己去阻塞队列获取任务执行
         * (2) 、阻塞队列满了，就直接开新线程执行，最大只能开到 max 指定的数量
         * (3) 、max 都执行好了。Max-core 数量空闲的线程会在 keepAliveTime 指定的时间后自动销毁。最终保持到core 大小
         * (4) 、如果线程数开到了 max 的数量，还有新任务进来，就会使用 reject 指定的拒绝策略进行处理
         * 3、所有的线程创建都是由指定的 factory 创建的。
         *
         * 面试：
         * 一个线程池 core 7； ； max 20  ，queue ：50 ，100 并发进来怎么分配的；
         * 先有 7 个能直接得到执行，接下来 50 个进入队列排队，在多开 13 个继续执行。现在 70 个
         * 被安排上了。剩下 30 个使用拒绝策略。
         *
         */

//        //以后在我们系统，以上三种启动线程都不用，【将所有的多线程异步任务都交给线程池执行】
//        executor.execute(new Runable01());

        ExecutorService threadPool = new ThreadPoolExecutor(
                200,
                10,
                10L,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(10000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
        threadPool.execute(new Runable01());
        System.out.println("main............end......");
    }

    public static class Thread01 extends Thread{
        @Override
        public void run(){
            System.out.println("当前线程："+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("执行结果："+i);
        }

    }

    public static class Runable01 implements Runnable{

        @Override
        public void run() {
            System.out.println("当前线程："+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("执行结果："+i);
        }
    }

    public static class Callable01 implements Callable<Integer>{

        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程："+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("执行结果："+i);
            return i;
        }
    }
}
